package com.lt.lumentracks.utils;


import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;


//阿里云OSS工具类
@Slf4j
@Component
public class AliOSSUtils {


    @Autowired
    private AliOSSProperties aliOSSProperties;


    /**
     * 实现上传文件到OSS
     * @param file  上传的文件
     * @param directoryName 文件上传的目录
     */
    public String upload(MultipartFile file, String directoryName) throws IOException, ClientException {

        // 从环境变量中获取访问凭证。运行本代码之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider evcProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        /*
            阿里云OSS的endpoint，以华东1（杭州）为例，Endpoint为：https://oss-cn-hangzhou.aliyuncs.com
            外网Endpoint固定为oss-rg-china-mainland.aliyuncs.com
        */
        String endpoint = aliOSSProperties.getEndpoint();

        /*
            填写Bucket所在地域。以华东1（杭州）为例，Region填写为cn-hangzhou,
            无地域属性Bucket的Region固定为 oss-rg-china-mainland，仅支持通过外网访问
        */
        String region = aliOSSProperties.getRegion();

//        String accessKeyId = aliOSSProperties.getAccessKeyId(); //阿里云的KeyID
//        String accessKeySecret = aliOSSProperties.getAccessKeySecret(); //阿里云的密钥
        String bucketName = aliOSSProperties.getBucketName(); //存储空间的名字



        if(directoryName == null){ directoryName = "";}

        //1、获取上传的文件的输入流
        InputStream inputStream = file.getInputStream();

        //2、避免文件覆盖（使用UUID）
        String originalFileName = file.getOriginalFilename();
        String filenameWithoutSuffix = originalFileName.substring(0, originalFileName.lastIndexOf('.')); // 截取不包含文件后缀名的部分
        String suffix = originalFileName.substring(originalFileName.lastIndexOf(".")); // 截取文件后缀名
        String fileName = directoryName + filenameWithoutSuffix + UUID.randomUUID() + suffix;

        //3、上传文件到OSS!!!
        ClientBuilderConfiguration cbConfiguration = new ClientBuilderConfiguration();
        cbConfiguration.setSignatureVersion(SignVersion.V4); // 设置签名算法版本为 V4
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(evcProvider)
                .clientConfiguration(cbConfiguration)
                .region(region) // V4签名版本要求明确指定Region，若不想使用region参数可切换签名算法版本回V1版本
                .build(); // 创建OSSClient实例
        ossClient.putObject(bucketName,fileName,inputStream);

        //4、获取文件访问路径
        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        //endpoint.split("//")[0] 获取协议部分（例如 https:）。
        //endpoint.split("//")[1] 获取域名部分（例如 oss-cn-hangzhou.aliyuncs.com）
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;

        //5、关闭ossClient
        ossClient.shutdown();
        return url; //6、返回上传到oss的路径

    }


    /**
     * 删除文件
     * @param fileFullPath  要删除的文件的全路径，例如："https://存储桶名字.阿里云oss服务器地址/目录名(可以为空也可以多层)/文件名"
     * @return 删除成功返回true，否则返回false
     */
    public boolean deleteObject(String fileFullPath) throws ClientException {

        // 从传进来的全路径中获取文件名（如果文件在目录中，要把目录也带上）
        //传进来的fullPath一般格式是这样："https://存储桶名字.阿里云oss服务器地址/目录名(可以为空也可以多层)/文件名"
        String fileName1 = fileFullPath.split("//")[1]; //截取 “存储桶名字.阿里云oss服务器地址/目录名(可以为空也可以多层)/文件名” 这一部分

        // 填写文件完整路径，例如example/example.txt。文件完整路径中不能包含Bucket名称。
        String objectName = fileName1.substring(fileName1.indexOf("/") + 1); //截取 “目录名/文件名” 这一部分


        // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
        String endpoint = aliOSSProperties.getEndpoint();
        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称，例如example-bucket。
        String bucketName = aliOSSProperties.getBucketName();
        // 填写Bucket所在地域。以华东1（杭州）为例，Region填写为cn-hangzhou。
        String region = aliOSSProperties.getRegion();


        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时，调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            log.info("要删除的文件为：{}", bucketName + "/" + objectName);

            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, objectName);


            // 在OSS Java SDK中使用OSSClient的deleteObject方法删除单个文件时，如果该方法没有抛出异常，则说明已成功删除该文件。
            // 如果您需要进一步确认该文件是否已成功删除，可以调用OSSClient的doesObjectExist方法，该方法可以判断指定的文件是否存在。
            // 如果该方法返回false，则说明该文件已成功删除。
            boolean isFound = ossClient.doesObjectExist(bucketName, objectName);
            if (!isFound) {
                log.info("文件 {} 删除成功", fileFullPath);
                return true;
            }else {
                log.error("文件 {} 删除失败", fileFullPath);
                return false;
            }
        } catch (OSSException oe) {
            System.out.println("捕获到OSSException异常，您的请求已成功发送到OSS服务，但由于某些原因被拒绝并返回了错误响应。");
            System.out.println("错误信息:" + oe.getErrorMessage());
            System.out.println("错误代码:" + oe.getErrorCode());
            System.out.println("请求ID:" + oe.getRequestId());
            System.out.println("主机ID:" + oe.getHostId());
        } finally {
            ossClient.shutdown();
        }
        return false;
    }


}
